﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;

namespace RockBus.DataContracts
{
    /// <summary>
    /// Describes the information, registered by a Publisher.
    ///  If any of the FilterIds in the TopicDictionary match to an incoming message,
    ///  that Topic will be applied to the message, and will be used in the topic subscription evaluation.
    /// </summary>
    [DataContract(Namespace = StringConstants.RockBusNamespace)]
    public class PublisherInfo : EvaluationElement<ReceivePortInfo, ReceivePortDetail>
    {
        private PublisherInfo()
            : base()
        {
            this.Init();
        }

        public PublisherInfo(string id,
            bool isStatic = false,
            IEnumerable<EndpointInfo> endpointInfos = null,
            IEnumerable<PipelineInfo> pipelineInfos = null,
            IEnumerable<ResponseInfo> responseInfos = null,
            IEnumerable<ReceivePortInfo> infos = null,
            DateTime? modificationDateTimeUtc = null
            )
            : base(id, isStatic, endpointInfos: endpointInfos, pipelineInfos: pipelineInfos, infos: infos, modificationDateTimeUtc: modificationDateTimeUtc)
        {
            this.Init();
            if (null != responseInfos)
            {
                foreach (var ri in responseInfos)
                {
                    this.ResponseInfoDictionary.Add(ri.Id, ri);
                }
            }
        }

        [OnDeserialized]
        private void OnDeserialized(StreamingContext context)
        {
            this.Init();
        }

        private void Init()
        {
            foreach (ReceivePortInfo pci in this.InfoDictionary.Values)
            {
                pci.PublisherInfo = this;
            }
            if (null == this.ResponseInfoDictionary)
            {
                this.ResponseInfoDictionary = new CaseInsensitiveStringDictionary<ResponseInfo>();
            }
        }

        /// <summary>
        /// Contains the ResponseInfo objects.
        ///  Key: Response Id. Value: ResponseInfo.
        /// </summary>
        [DataMember]
        public CaseInsensitiveStringDictionary<ResponseInfo> ResponseInfoDictionary { get; set; }

        public void AddReceivePortInfo(ReceivePortDetail detail, string responseId = null, bool generateDefaultResponse = false)
        {
            var receivePortInfo = new ReceivePortInfo(this, detail, responseId, generateDefaultResponse);
            this.InfoDictionary.Add(receivePortInfo.Id, receivePortInfo);
        }

        public override void PurgeExpired(DateTime utcNow)
        {
            foreach (var adv in this.InfoDictionary.Values.ToArray())
            {
                if (adv.Detail.ExpiryDateTimeUtc < utcNow)
                {
                    this.InfoDictionary.Remove(adv.Detail.Id);
                }
            }
        }
    }
}